use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
use std::{fs::File, io::BufReader, io::Write, sync::{Arc, RwLock}};
use uuid::Uuid;

type SharedTodos = Arc<RwLock<Vec<Task>>>;

#[derive(Debug, Clone, Serialize, Deserialize)]
struct Task {
    id: Uuid,
    title: String,
    tags: Vec<String>,
    done: bool,
    created_at: DateTime<Utc>,
    // Pomodoro related fields
    pomodoro_count: u32,
    sessions: Vec<DateTime<Utc>>,
}

impl Task {
    fn new(title: String, tags: Vec<String>) -> Self {
        Self {
            id: Uuid::new_v4(),
            title,
            tags,
            done: false,
            created_at: Utc::now(),
            pomodoro_count: 0,
            sessions: Vec::new(),
        }
    }
}

fn parse_duration_seconds(token: &str) -> Option<u64> {
    // Accept forms like "15" (minutes), "15m", "90s"
    if token.ends_with('s') {
        token[..token.len()-1].parse::<u64>().ok()
    } else if token.ends_with('m') {
        token[..token.len()-1].parse::<u64>().ok().map(|m| m * 60)
    } else {
        // treat as minutes if integer
        token.parse::<u64>().ok().map(|m| m * 60)
    }
}

fn save_to_file(path: &str, todos: &SharedTodos) -> anyhow::Result<()> {
    let items = todos.read().unwrap();
    let file = File::create(path)?;
    serde_json::to_writer_pretty(file, &*items)?;
    Ok(())
}

fn load_from_file(path: &str) -> anyhow::Result<Vec<Task>> {
    match File::open(path) {
        Ok(f) => {
            let reader = BufReader::new(f);
            let items = serde_json::from_reader(reader)?;
            Ok(items)
        }
        Err(_) => Ok(Vec::new()),
    }
}

fn export_csv(path: &str, todos: &SharedTodos) -> anyhow::Result<()> {
    let items = todos.read().unwrap();
    let mut f = File::create(path)?;
    // header
    writeln!(f, "id,title,pomodoro_count,session_count,last_session,sessions")?;
    for t in items.iter() {
        let last = t.sessions.last().map(|d| d.to_string()).unwrap_or_default();
        let sessions_joined = t.sessions.iter().map(|d| d.to_string()).collect::<Vec<_>>().join("|");
        // escape quotes by doubling
        let title = t.title.replace('\"', "\"\"");
        writeln!(f, "\"{}\",\"{}\",{},{} ,\"{}\",\"{}\"", t.id, title, t.pomodoro_count, t.sessions.len(), last, sessions_joined)?;
    }
    Ok(())
}

fn clean_question_mark_entries(todos: &SharedTodos) -> usize {
    let mut vec = todos.write().unwrap();
    let before = vec.len();
    vec.retain(|t| !t.title.contains('?'));
    before - vec.len()
}

fn main() -> anyhow::Result<()> {
    // Prepare shared storage
    let path = "todos.json";
    let initial = load_from_file(path).unwrap_or_default();
    let todos: SharedTodos = Arc::new(RwLock::new(initial));

    println!("===== Rust番茄学习时钟 =====");
    println!("功能：持久化(JSON)、标签、搜索、标记完成、删除、番茄钟计时与统计");
    println!("快捷命令示例（功能演示，每行一条）：");
    println!("  add 学习 Rust 所有权 #学习 #rust          —— 添加任务");
    println!("  list                                    —— 列出所有任务");
    println!("  list todo                               —— 列出未完成任务");
    println!("  list done                               —— 列出已完成任务");
    println!("  list tag 学习                            —— 按标签筛选");
    println!("  search 所有权                            —— 在标题/标签中搜索");
    println!("  done last                               —— 标记最近任务为完成");
    println!("  rm <id>                                 —— 删除指定任务");
    println!("  start last 3s                           —— 启动短番茄计时（演示用）");
    println!("  stats last                              —— 查看最近任务统计");
    println!("  export csv out.csv                      —— 导出为 CSV");
    println!("  clean                                   —— 清理脏数据并保存");
    println!("  save                                    —— 手动保存 todos.json");
    println!("  load                                    —— 从文件加载 todos.json");
    println!("  serve 8080                              —— （可选）后台启动 HTTP API（需启用）");
    println!("  exit                                    —— 退出并保存");
    println!("======================================\n");

    // NOTE: HTTP server option removed in this build; keep commands focused on CLI features.

    loop {
        print!("> ");
        // flush stdout so prompt shows
        std::io::stdout().flush()?;
        let mut input = String::new();
        std::io::stdin().read_line(&mut input)?;
        let input = input.trim();
        if input.is_empty() {
            continue;
        }

        let mut parts = input.split_whitespace();
        let cmd = parts.next().unwrap().to_lowercase();
        match cmd.as_str() {
            "add" => {
                // rest of the line after "add "
                let rest = input.strip_prefix("add ").unwrap_or("").trim();
                if rest.is_empty() {
                    println!("请提供待办内容，例如：add 买牛奶 #生活");
                    continue;
                };
                // extract tags starting with #
                let mut title_parts: Vec<&str> = Vec::new();
                let mut tags: Vec<String> = Vec::new();
                for token in rest.split_whitespace() {
                    if token.starts_with('#') && token.len() > 1 {
                        tags.push(token[1..].to_string());
                    } else {
                        title_parts.push(token);
                    }
                }
                let title = title_parts.join(" ");
                let task = Task::new(title, tags);
                todos.write().unwrap().push(task.clone());
                println!("已添加：{} ({})", task.title, task.id);
            }
            "list" => {
                let arg = parts.next();
                let vec = todos.read().unwrap();
                let filtered: Vec<Task> = match arg {
                    Some("all") | None => vec.clone(),
                    Some("todo") => vec.iter().cloned().filter(|t| !t.done).collect(),
                    Some("done") => vec.iter().cloned().filter(|t| t.done).collect(),
                    Some("tag") => {
                        if let Some(tag) = parts.next() {
                            vec.iter().cloned().filter(|t| t.tags.iter().any(|x| x == tag)).collect()
                        } else {
                            println!("请在 tag 后提供标签名，例如：list tag 家庭");
                            continue;
                        }
                    }
                    Some(other) => {
                        println!("未知参数：{}， 使用 list [all|todo|done|tag <tag>]", other);
                        continue;
                    }
                };
                if filtered.is_empty() {
                    println!("没有找到符合条件的任务");
                } else {
                    for t in filtered.iter() {
                        println!("- {} | {} | tags: {:?} | {}", t.id, t.title, t.tags, if t.done {"done"} else {"todo"});
                    }
                }
            }
            "done" => {
                if let Some(id_str) = parts.next() {
                    // allow shortcut "last" to mean most recently added task
                    let maybe_id = if id_str == "last" {
                        let vec = todos.read().unwrap();
                        vec.last().map(|t| t.id)
                    } else {
                        Uuid::parse_str(id_str).ok()
                    };
                    if let Some(id) = maybe_id {
                        {
                            let mut vec = todos.write().unwrap();
                            if let Some(t) = vec.iter_mut().find(|t| t.id == id) {
                                t.done = true;
                                println!("已标记完成：{}", id);
                            } else {
                                println!("未找到 id={}", id);
                            }
                        }
                    }
                } else {
                    println!("请提供任务 id，例如：done <id>");
                }
            }
            "rm" | "remove" => {
                if let Some(id_str) = parts.next() {
                    match Uuid::parse_str(id_str) {
                        Ok(id) => {
                            let mut vec = todos.write().unwrap();
                            let before = vec.len();
                            vec.retain(|t| t.id != id);
                            if vec.len() != before {
                                println!("已删除：{}", id);
                            } else {
                                println!("未找到 id={}", id);
                            }
                        }
                        Err(_) => println!("无效的 UUID: {}", id_str),
                    }
                } else {
                    println!("请提供任务 id，例如：rm <id>");
                }
            }
            "search" => {
                let query = parts.collect::<Vec<&str>>().join(" ");
                if query.is_empty() {
                    println!("请提供搜索关键词，例如：search 牛奶");
                    continue;
                }
                let q = query.to_lowercase();
                let vec = todos.read().unwrap();
                let matched: Vec<_> = vec
                    .iter()
                    .filter(|t| t.title.to_lowercase().contains(&q) || t.tags.iter().any(|tag| tag.contains(&q)))
                    .cloned()
                    .collect();
                if matched.is_empty() {
                    println!("未找到匹配：{}", query);
                } else {
                    for t in matched.iter() {
                        println!("- {} | {} | tags: {:?} | {}", t.id, t.title, t.tags, if t.done {"done"} else {"todo"});
                    }
                }
            }
            "start" => {
                // start <id|last> [duration]
                if let Some(id_str) = parts.next() {
                    let maybe_id = if id_str == "last" {
                        let vec = todos.read().unwrap();
                        vec.last().map(|t| t.id)
                    } else {
                        Uuid::parse_str(id_str).ok()
                    };
                    if let Some(id) = maybe_id {
                        // parse optional duration token
                        let dur_token = parts.next();
                        let seconds = dur_token.and_then(|t| parse_duration_seconds(t)).unwrap_or(25*60);
                        // spawn background thread to wait and then record session
                        let todos_clone = todos.clone();
                        let path_clone = path.to_string();
                        std::thread::spawn(move || {
                            std::thread::sleep(std::time::Duration::from_secs(seconds));
                            let now = Utc::now();
                            if let Ok(mut vec) = todos_clone.write() {
                                if let Some(t) = vec.iter_mut().find(|t| t.id == id) {
                                    t.pomodoro_count += 1;
                                    t.sessions.push(now);
                                }
                            }
                            // try save (best-effort)
                            let _ = save_to_file(&path_clone, &todos_clone);
                        });
                        println!("已开始番茄钟：{} （{} 秒），后台运行中...", id, seconds);
                    } else {
                        println!("无效的 UUID 或未找到 last: {}", id_str);
                    }
                } else {
                    println!("请提供任务 id，例如：start <id|last> [25m|1500s]");
                }
            }
            "stats" => {
                if let Some(id_str) = parts.next() {
                    let maybe_id = if id_str == "last" {
                        let vec = todos.read().unwrap();
                        vec.last().map(|t| t.id)
                    } else {
                        Uuid::parse_str(id_str).ok()
                    };
                    if let Some(id) = maybe_id {
                        let vec = todos.read().unwrap();
                        if let Some(t) = vec.iter().find(|t| t.id == id) {
                            println!("任务 {} 番茄数：{}", id, t.pomodoro_count);
                            if t.sessions.is_empty() {
                                println!("无历史记录");
                            } else {
                                println!("最近会话：");
                                for s in t.sessions.iter() {
                                    println!("  - {}", s);
                                }
                            }
                        } else {
                            println!("未找到 id={}", id);
                        }
                    } else {
                        println!("无效的 UUID 或未找到 last: {}", id_str);
                    }
                } else {
                    println!("请提供任务 id，例如：stats <id|last>");
                }
            }
            "save" => {
                if let Err(e) = save_to_file(path, &todos) {
                    println!("保存失败：{}", e);
                } else {
                    println!("已保存到 {}", path);
                }
            }
            "wait" => {
                // wait <seconds>  —— 在主线程阻塞指定秒数，便于 demo 中等待后台线程完成
                if let Some(sec_str) = parts.next() {
                    if let Ok(sec) = sec_str.parse::<u64>() {
                        println!("等待 {} 秒（期间不接受新命令）...", sec);
                        std::thread::sleep(std::time::Duration::from_secs(sec));
                        println!("等待结束");
                    } else {
                        println!("无效的秒数：{}", sec_str);
                    }
                } else {
                    println!("用法：wait <seconds>");
                }
            }
            "export" => {
                // export csv <path>
                if let Some(fmt) = parts.next() {
                    if fmt == "csv" {
                        let out = parts.next().unwrap_or("export.csv");
                        match export_csv(out, &todos) {
                            Ok(_) => println!("已导出 CSV 到 {}", out),
                            Err(e) => println!("导出失败：{}", e),
                        }
                    } else {
                        println!("目前只支持：export csv <file>");
                    }
                } else {
                    println!("用法：export csv <file>");
                }
            }
            "clean" => {
                // remove entries with '?' in title
                let removed = clean_question_mark_entries(&todos);
                if removed > 0 {
                    let _ = save_to_file(path, &todos);
                    println!("已清理 {} 条脏数据并保存", removed);
                } else {
                    println!("未发现脏数据");
                }
            }
            "load" => {
                match load_from_file(path) {
                    Ok(list) => {
                        let mut vec = todos.write().unwrap();
                        *vec = list;
                        println!("已从 {} 加载（共 {} 项）", path, vec.len());
                    }
                    Err(e) => println!("加载失败：{}", e),
                }
            }
            "serve" => {
                println!("本构建未启用 HTTP API；如需启用可在 Cargo.toml 中加入 axum 并恢复相关代码。");
            }
            "exit" => {
                // save on exit
                if let Err(e) = save_to_file(path, &todos) {
                    println!("退出时保存失败：{}", e);
                } else {
                    println!("已保存，退出。再见！");
                }
                break;
            }
            "help" => {
                println!("可用命令：add/list/done/rm/search/save/load/serve/exit");
            }
            other => {
                println!("未知命令：{}，输入 help 查看可用命令", other);
            }
        }
    }

    Ok(())
}